from numpy import (
    ndarray,  # Numpy的n维数组对象
    array,  # 创建数组
    newaxis,  # 创建新轴
    zeros,  # 生成全零数组
    sqrt,  # 计算平方根
    exp,  # 计算指数
    pi,  # 圆周率常量
)

from src.data.satellite import (
    Satellite,  # 导入Satellite类，用于表示卫星对象
)


def los_channel_model(
        satellite: Satellite,  # 卫星对象
        users: list,  # 用户对象列表，每个用户表示一个通信用户
) -> ndarray:
    """
    计算用户与卫星之间的视距（Line-of-Sight, LOS）信道模型
    返回值为一个复杂的信道状态信息矩阵，维度为 (用户数量, 天线数量)
    """

    # 创建信道状态信息的全零矩阵，维度为(用户数量, 卫星天线数量)，数据类型为复数
    channel_state_information = zeros((len(users), satellite.antenna_nr), dtype='complex')
    
    # 遍历所有用户，计算每个用户的信道状态信息
    for user in users:
        # 计算信号的功率比：天线增益、用户增益以及距离的平方衰减影响
        power_ratio = (
                satellite.antenna_gain_linear  # 卫星天线的线性增益
                * user.gain_linear  # 用户设备的线性增益
                * (satellite.wavelength / (4 * pi * satellite.distance_to_users[user.idx])) ** 2  # 根据用户与卫星的距离计算信号的衰减
        )

        # 计算幅度衰减，取功率比的平方根
        amplitude_damping = sqrt(power_ratio)

        # 计算相位偏移，根据用户与卫星的距离除以波长，并转换为相位变化
        phase_shift = satellite.distance_to_users[user.idx] % satellite.wavelength * 2 * pi / satellite.wavelength

        # 计算最终的信道状态信息
        channel_state_information[user.idx, :] = (
            amplitude_damping  # 幅度衰减
            * exp(1j * phase_shift)  # 相位偏移的指数表示，使用复数
            * satellite.steering_vectors_to_users[user.idx]  # 卫星阵列到用户的导向向量
        )

    # 返回用户与卫星之间的信道状态信息矩阵
    return channel_state_information
